//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================


#include <core.h>

EXTERN CMemoryAllocatorLock *g_pDlMallocLock;
EXTERN CMemoryAllocatorLock *g_pDlMagicInitLock;


#ifdef KERNEL_MEMORY_DETECT
EXTERN CMemoryAllocatorLock g_kmemLock;
#endif

#ifdef _DEBUG
#define _MEMORY_ALLOCATOR_LOCK(_mutex)      (_mutex).AllocatorLock()
#define _MEMORY_ALLOCATOR_UNLOCK(_mutex)    (_mutex).AllocatorUnlock()
#else
#define _MEMORY_ALLOCATOR_LOCK(_mutex)      (_mutex).Lock()
#define _MEMORY_ALLOCATOR_UNLOCK(_mutex)    (_mutex).Unlock()
#endif // _DEBUG

EXTERN bool_t LockMemoryAllocatorAndDisablePreemption()
{
    assert(PreemptionEnabled());

    _MEMORY_ALLOCATOR_LOCK(*g_pDlMagicInitLock);
    _MEMORY_ALLOCATOR_LOCK(*g_pDlMallocLock);

    Zone * pZone = &g_zones[dz.uNumberOfZones - 1];
    while (pZone >= g_zones) {
        _MEMORY_ALLOCATOR_LOCK(pZone->m_lock);
        pZone--;
    }

#ifdef KERNEL_MEMORY_DETECT
    _MEMORY_ALLOCATOR_LOCK(g_kmemLock);
#endif

    return DzDisablePreemption();
}

EXTERN void UnlockMemoryAllocatorAndRestorePreemption(bool_t bPreemption)
{
#ifdef KERNEL_MEMORY_DETECT
    _MEMORY_ALLOCATOR_UNLOCK(g_kmemLock);
#endif

    Zone * pZone = g_zones;
    while (pZone < g_zones + dz.uNumberOfZones) {
        _MEMORY_ALLOCATOR_UNLOCK(pZone->m_lock);
        pZone++;
    }

    _MEMORY_ALLOCATOR_UNLOCK(*g_pDlMallocLock);
    _MEMORY_ALLOCATOR_UNLOCK(*g_pDlMagicInitLock);

    DzRestorePreemption(bPreemption);
}

EXTERN_C void* dlmalloc(size_t);
EXTERN_C void  dlfree(void*);


EXTERN_C void *malloc(size_t size)
{
#if defined(KERNEL_MEMORY_DETECT)
    if (size == 0) {
        kprintf("warning: malloc size = 0\n");
    };
#endif

    void *pv = (void *)dlmalloc(size);

    KMEM_INSERT_INTO_HASH

    return pv;
}

EXTERN_C void free(void *pv)
{
    KMEM_DETACH_FROM_HASH

    dlfree(pv);
}

void *operator new(size_t size)
{
    return malloc(size);
}

void operator delete(void *pv)
{
    free(pv);
}

void *operator new [](size_t size)
{
    return malloc(size);
}

void operator delete [](void *pv)
{
    free(pv);
}

void* __cdecl operator new(size_t, void* _location)
{
    return _location;
}

void __cdecl operator delete(void*, void*)
{
}
